home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Dev / gcc263-src.lha / gcc-2.6.3 / config / h8300 / lib1funcs.asm < prev    next >
Assembly Source File  |  1994-07-16  |  12KB  |  703 lines

  1. ;; libgcc1 routines for the Hitachi h8/300 cpu.
  2. ;; Contributed by Steve Chamberlain.
  3. ;; sac@cygnus.com
  4.  
  5. /* Copyright (C) 1994 Free Software Foundation, Inc.
  6.  
  7. This file is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. In addition to the permissions in the GNU General Public License, the
  13. Free Software Foundation gives you unlimited permission to link the
  14. compiled version of this file with other programs, and to distribute
  15. those programs without any restriction coming from the use of this
  16. file.  (The General Public License restrictions do apply in other
  17. respects; for example, they cover modification of the file, and
  18. distribution when not linked into another program.)
  19.  
  20. This file is distributed in the hope that it will be useful, but
  21. WITHOUT ANY WARRANTY; without even the implied warranty of
  22. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  23. General Public License for more details.
  24.  
  25. You should have received a copy of the GNU General Public License
  26. along with this program; see the file COPYING.  If not, write to
  27. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  28.  
  29. /* As a special exception, if you link this library with other files,
  30.    some of which are compiled with GCC, to produce an executable,
  31.    this library does not by itself cause the resulting executable
  32.    to be covered by the GNU General Public License.
  33.    This exception does not however invalidate any other reasons why
  34.    the executable file might be covered by the GNU General Public License.  */
  35.  
  36. /* Assembler register definitions.  */
  37.  
  38. #define A0 r0
  39. #define A0L r0l
  40. #define A0H r0h
  41.  
  42. #define A1 r1
  43. #define A1L r1l
  44. #define A1H r1h
  45.  
  46. #define A2 r2
  47. #define A2L r2l
  48. #define A2H r2h
  49.  
  50. #define A3 r3
  51. #define A3L r3l
  52. #define A3H r3h
  53.  
  54. #define S0 r4
  55. #define S0L r4l
  56. #define S0H r4h
  57.  
  58. #define S1 r5
  59. #define S1L r5l
  60. #define S1H r5h
  61.  
  62. #define S2 r6
  63. #define S2L r6l
  64. #define S2H r6h
  65.  
  66. #ifdef __H8300__
  67. #define MOVP    mov.w    /* pointers are 16 bits */
  68. #define ADDP    add.w
  69. #define CMPP    cmp.w
  70. #define PUSHP    push
  71. #define POPP    pop
  72.  
  73. #define A0P    r0
  74. #define A1P    r1
  75. #define A2P    r2
  76. #define A3P    r3
  77. #define S0P    r4
  78. #define S1P    r5
  79. #define S2P    r6
  80. #endif
  81.  
  82. #ifdef __H8300H__
  83. #define MOVP    mov.l    /* pointers are 32 bits */
  84. #define ADDP    add.l
  85. #define CMPP    cmp.l
  86. #define PUSHP    push.l
  87. #define POPP    pop.l
  88.  
  89. #define A0P    er0
  90. #define A1P    er1
  91. #define A2P    er2
  92. #define A3P    er3
  93. #define S0P    er4
  94. #define S1P    er5
  95. #define S2P    er6
  96.  
  97. #define A0E    e0
  98. #define A1E    e1
  99. #define A2E    e2
  100. #define A3E    e3
  101. #endif
  102.  
  103. #ifdef L_cmpsi2
  104. #ifdef __H8300__
  105.     .section .text
  106.     .align 2
  107.     .global ___cmpsi2
  108. ___cmpsi2:
  109.     cmp.w    A2,A0
  110.     bne    .L2
  111.     cmp.w    A3,A1
  112.     bne    .L2
  113.     mov.w    #1,A0
  114.     rts
  115. .L2:
  116.     cmp.w    A0,A2
  117.     bgt    .L4
  118.     bne    .L3
  119.     cmp.w    A1,A3
  120.     bls    .L3
  121. .L4:
  122.     sub.w    A0,A0
  123.     rts
  124. .L3:
  125.     mov.w    #2,A0
  126. .L5:
  127.     rts
  128.     .end
  129. #endif
  130. #endif /* L_cmpsi2 */
  131.  
  132. #ifdef L_ucmpsi2
  133. #ifdef __H8300__
  134.     .section .text
  135.     .align 2
  136.     .global ___ucmpsi2
  137. ___ucmpsi2:
  138.     cmp.w    A2,A0
  139.     bne    .L2
  140.     cmp.w    A3,A1
  141.     bne    .L2
  142.     mov.w    #1,A0
  143.     rts
  144. .L2:
  145.     cmp.w    A0,A2
  146.     bhi    .L4
  147.     bne    .L3
  148.     cmp.w    A1,A3
  149.     bls    .L3
  150. .L4:
  151.     sub.w    A0,A0
  152.     rts
  153. .L3:
  154.     mov.w    #2,A0
  155. .L5:
  156.     rts
  157.     .end
  158. #endif
  159. #endif /* L_ucmpsi2 */
  160.  
  161. #ifdef L_divhi3
  162.  
  163. ;; HImode divides for the H8/300.
  164. ;; We bunch all of this into one object file since there are several
  165. ;; "supporting routines".
  166.  
  167. ; general purpose normalize routine
  168. ; divisor in A0
  169. ; dividend in A1
  170. ; turns both into +ve numbers, and leaves what the answer sign
  171. ; should be in A2L
  172.  
  173. #ifdef __H8300__
  174.     .section .text
  175.     .align 2
  176. divnorm:
  177.     mov.b    #0x0,A2L
  178.     or    A0H,A0H        ; is divisor > 0
  179.     bge    _lab1            
  180.     not    A0H        ; no - then make it +ve
  181.     not    A0L
  182.     adds    #1,A0            
  183.     xor    #0x1,A2L    ; and remember that in A2L
  184. _lab1:    or    A1H,A1H    ; look at dividend
  185.     bge    _lab2        
  186.     not    A1H        ; it is -ve, make it positive
  187.     not    A1L
  188.     adds    #1,A1
  189.     xor    #0x1,A2L; and toggle sign of result
  190. _lab2:    rts
  191.  
  192. ; A0=A0/A1 signed
  193.  
  194.     .global    ___divhi3
  195. ___divhi3:
  196.     bsr    divnorm
  197.     bsr    ___udivhi3
  198. negans:    or    A2L,A2L    ; should answer be negative ?
  199.     beq    _lab4
  200.     not    A0H    ; yes, so make it so
  201.     not    A0L
  202.     adds    #1,A0
  203. _lab4:    rts    
  204.  
  205. ; A0=A0%A1 signed
  206.  
  207.     .global    ___modhi3
  208. ___modhi3:
  209.     bsr    divnorm
  210.     bsr    ___udivhi3
  211.     mov    A3,A0
  212.     bra    negans
  213.  
  214. ; A0=A0%A1 unsigned
  215.  
  216.     .global    ___umodhi3
  217. ___umodhi3:
  218.     bsr    ___udivhi3
  219.     mov    A3,A0
  220.     rts
  221.  
  222. ; A0=A0/A1 unsigned
  223. ; A3=A0%A1 unsigned
  224. ; A2H trashed
  225. ; D high 8 bits of denom
  226. ; d low 8 bits of denom
  227. ; N high 8 bits of num
  228. ; n low 8 bits of num
  229. ; M high 8 bits of mod
  230. ; m low 8 bits of mod
  231. ; Q high 8 bits of quot
  232. ; q low 8 bits of quot
  233. ; P preserve
  234.  
  235. ; The h8 only has a 16/8 bit divide, so we look at the incoming and
  236. ; see how to partition up the expression.
  237.  
  238.     .global    ___udivhi3
  239. ___udivhi3:
  240.                 ; A0 A1 A2 A3 
  241.                 ; Nn Dd       P
  242.     sub.w    A3,A3        ; Nn Dd xP 00 
  243.     or    A1H,A1H         
  244.     bne    divlongway
  245.     or    A0H,A0H        
  246.     beq    _lab6        
  247.  
  248. ; we know that D == 0 and N is != 0
  249.     mov.b    A0H,A3L        ; Nn Dd xP 0N
  250.     divxu    A1L,A3        ;          MQ
  251.     mov.b    A3L,A0H         ; Q
  252. ; dealt with N, do n
  253. _lab6:    mov.b    A0L,A3L        ;           n
  254.     divxu    A1L,A3        ;          mq
  255.     mov.b    A3L,A0L        ; Qq
  256.     mov.b    A3H,A3L         ;           m
  257.     mov.b    #0x0,A3H    ; Qq       0m
  258.     rts    
  259.  
  260. ; D != 0 - which means the denominator is
  261. ;          loop around to get the result.
  262.  
  263. divlongway:
  264.     mov.b    A0H,A3L        ; Nn Dd xP 0N
  265.     mov.b    #0x0,A0H    ; high byte of answer has to be zero
  266.     mov.b    #0x8,A2H    ;       8
  267. div8:    add.b    A0L,A0L        ; n*=2
  268.     rotxl    A3L        ; Make remainder bigger
  269.     rotxl    A3H        
  270.     sub.w    A1,A3        ; Q-=N
  271.     bhs    setbit        ; set a bit ?
  272.     add.w    A1,A3        ;  no : too far , Q+=N
  273.  
  274.     dec    A2H        
  275.     bne    div8        ; next bit    
  276.     rts    
  277.  
  278. setbit:    inc    A0L        ; do insert bit
  279.     dec    A2H        
  280.     bne    div8        ; next bit    
  281.     rts    
  282.  
  283. #endif /* __H8300__ */
  284. #endif /* L_divhi3 */
  285.  
  286. #ifdef L_divsi3
  287.  
  288. ;; 4 byte integer divides for the H8/300.
  289. ;;
  290. ;; We have one routine which does all the work and lots of 
  291. ;; little ones which prepare the args and massage the sign.
  292. ;; We bunch all of this into one object file since there are several
  293. ;; "supporting routines".
  294.  
  295. #ifdef __H8300H__
  296.     .h8300h
  297. #endif
  298.  
  299.     .section .text
  300.     .align 2
  301.  
  302. ; Put abs SIs into r0/r1 and r2/r3, and leave a 1 in r6l with sign of rest.
  303. ; This function is here to keep branch displacements small.
  304.  
  305. #ifdef __H8300__
  306.  
  307. divnorm:
  308.     mov.b    #0,S2L        ; keep the sign in S2
  309.     mov.b    A0H,A0H        ; is the numerator -ve
  310.     bge    postive
  311.  
  312.     ; negate arg
  313.     not    A0H
  314.     not    A1H
  315.     not    A0L
  316.     not    A1L
  317.  
  318.     add    #1,A1L
  319.     addx    #0,A1H
  320.     addx    #0,A0H
  321.     addx    #0,A0L
  322.  
  323.     mov.b    #1,S2L        ; the sign will be -ve
  324. postive:
  325.     mov.b    A2H,A2H        ; is the denominator -ve
  326.     bge    postive2
  327.     not    A2L        
  328.     not    A2H
  329.     not    A3L
  330.     not    A3H
  331.     add.b    #1,A3L    
  332.     addx    #0,A3H
  333.     addx    #0,A2L
  334.     addx    #0,A2H
  335.     xor    #1,S2L        ; toggle result sign
  336. postive2:
  337.     rts
  338.  
  339. #else /* __H8300H__ */
  340.  
  341. divnorm:
  342.     mov.b    #0,S2L        ; keep the sign in S2
  343.     mov.l    A0P,A0P        ; is the numerator -ve
  344.     bge    postive
  345.  
  346.     neg.l    A0P        ; negate arg
  347.     mov.b    #1,S2L        ; the sign will be -ve
  348.  
  349. postive:
  350.     mov.l    A1P,A1P        ; is the denominator -ve
  351.     bge    postive2
  352.  
  353.     neg.l    A1P        ; negate arg
  354.     xor.b    #1,S2L        ; toggle result sign
  355.  
  356. postive2:
  357.     rts
  358.  
  359. #endif
  360.  
  361. ; numerator in A0/A1
  362. ; denominator in A2/A3
  363.     .global    ___modsi3
  364. ___modsi3:
  365.     PUSHP    S2P        
  366.     PUSHP    S0P
  367.     PUSHP    S1P
  368.  
  369.     bsr    divnorm
  370.     bsr    divmodsi4
  371. #ifdef __H8300__
  372.     mov    S0,A0
  373.     mov    S1,A1
  374. #else
  375.     mov.l    S0P,A0P
  376. #endif
  377.     bra    exitdiv
  378.  
  379.     .global    ___udivsi3
  380. ___udivsi3:
  381.     PUSHP    S2P
  382.     PUSHP    S0P
  383.     PUSHP    S1P
  384.     mov.b    #0,S2L    ; keep sign low
  385.     bsr    divmodsi4
  386.     bra    exitdiv
  387.  
  388.     .global    ___umodsi3
  389. ___umodsi3:
  390.     PUSHP    S2P
  391.     PUSHP    S0P
  392.     PUSHP    S1P
  393.     mov.b    #0,S2L    ; keep sign low
  394.     bsr    divmodsi4
  395. #ifdef __H8300__
  396.     mov    S0,A0
  397.     mov    S1,A1
  398. #else
  399.     mov.l    S0P,A0P
  400. #endif
  401.     bra    exitdiv
  402.     
  403.     .global    ___divsi3
  404. ___divsi3:
  405.     PUSHP    S2P
  406.     PUSHP    S0P
  407.     PUSHP    S1P
  408.     jsr    divnorm
  409.     jsr    divmodsi4
  410.  
  411.     ; examine what the sign should be
  412. exitdiv:
  413.     POPP    S1P
  414.     POPP    S0P
  415.  
  416.     or    S2L,S2L
  417.     beq    reti
  418.     
  419.     ; should be -ve
  420. #ifdef __H8300__
  421.     not    A0H
  422.     not    A1H
  423.     not    A0L
  424.     not    A1L
  425.  
  426.     add    #1,A1L
  427.     addx    #0,A1H
  428.     addx    #0,A0H
  429.     addx    #0,A0L
  430. #else /* __H8300H__ */
  431.     neg.l    A0P
  432. #endif
  433.  
  434. reti:
  435.     POPP    S2P
  436.     rts    
  437.  
  438.     ; takes A0/A1 numerator (A0P for 300h)
  439.     ; A2/A3 denominator (A1P for 300h)
  440.     ; returns A0/A1 quotient (A0P for 300h)
  441.     ; S0/S1 remainder (S0P for 300h)
  442.     ; trashes S2
  443.  
  444. #ifdef __H8300__
  445.  
  446. divmodsi4:
  447.         sub.w    S0,S0        ; zero play area
  448.         mov.w    S0,S1
  449.         mov.b    A2H,S2H
  450.         or    A2L,S2H
  451.         or    A3H,S2H
  452.         bne    DenHighZero
  453.         mov.b    A0H,A0H
  454.         bne    NumByte0Zero
  455.         mov.b    A0L,A0L
  456.         bne    NumByte1Zero
  457.         mov.b    A1H,A1H
  458.         bne    NumByte2Zero
  459.         bra    NumByte3Zero
  460. NumByte0Zero:
  461.     mov.b    A0H,S1L
  462.         divxu    A3L,S1
  463.         mov.b    S1L,A0H
  464. NumByte1Zero:
  465.     mov.b    A0L,S1L
  466.         divxu    A3L,S1
  467.         mov.b    S1L,A0L
  468. NumByte2Zero:
  469.     mov.b    A1H,S1L
  470.         divxu    A3L,S1
  471.         mov.b    S1L,A1H
  472. NumByte3Zero:
  473.     mov.b    A1L,S1L
  474.         divxu    A3L,S1
  475.         mov.b    S1L,A1L
  476.  
  477.         mov.b    S1H,S1L
  478.         mov.b    #0x0,S1H
  479.         rts    
  480.  
  481. ; have to do the divide by shift and test
  482. DenHighZero:
  483.     mov.b    A0H,S1L
  484.         mov.b    A0L,A0H
  485.         mov.b    A1H,A0L
  486.         mov.b    A1L,A1H
  487.  
  488.         mov.b    #0,A1L
  489.         mov.b    #24,S2H    ; only do 24 iterations
  490.  
  491. nextbit:
  492.     add.w    A1,A1    ; double the answer guess
  493.         rotxl    A0L
  494.         rotxl    A0H
  495.  
  496.         rotxl    S1L    ; double remainder
  497.         rotxl    S1H
  498.         rotxl    S0L
  499.         rotxl    S0H
  500.         sub.w    A3,S1    ; does it all fit
  501.         subx    A2L,S0L
  502.         subx    A2H,S0H
  503.         bhs    setone     
  504.  
  505.         add.w    A3,S1    ; no, restore mistake
  506.         addx    A2L,S0L
  507.         addx    A2H,S0H
  508.  
  509.         dec    S2H
  510.         bne    nextbit
  511.         rts    
  512.     
  513. setone:
  514.     inc    A1L
  515.         dec    S2H
  516.         bne    nextbit
  517.         rts    
  518.  
  519. #else /* __H8300H__ */
  520.  
  521. divmodsi4:
  522.     sub.l    S0P,S0P        ; zero play area
  523.     mov.w    A1E,A1E        ; denominator top word 0?
  524.     bne    DenHighZero
  525.  
  526.     ; do it the easy way, see page 107 in manual
  527.     mov.w    A0E,A2
  528.     extu.l    A2P
  529.     divxu.w    A1,A2P
  530.     mov.w    A2E,A0E
  531.     divxu.w    A1,A0P
  532.     mov.w    A0E,S0
  533.     mov.w    A2,A0E
  534.     extu.l    S0P
  535.     rts
  536.  
  537. DenHighZero:
  538.     mov.w    A0E,A2
  539.     mov.b    A2H,S0L
  540.     mov.b    A2L,A2H
  541.     mov.b    A0H,A2L
  542.     mov.w    A2,A0E
  543.     mov.b    A0L,A0H
  544.     mov.b    #0,A0L
  545.     mov.b    #24,S2H        ; only do 24 iterations
  546.  
  547. nextbit:
  548.     shll.l    A0P        ; double the answer guess
  549.     rotxl.l    S0P        ; double remainder
  550.     sub.l    A1P,S0P        ; does it all fit?
  551.     bhs    setone
  552.  
  553.     add.l    A1P,S0P        ; no, restore mistake
  554.     dec    S2H
  555.     bne    nextbit
  556.     rts
  557.  
  558. setone:
  559.     inc    A0L
  560.     dec    S2H
  561.     bne    nextbit
  562.     rts
  563.  
  564. #endif
  565. #endif /* L_divsi3 */
  566.  
  567. #ifdef L_mulhi3
  568.  
  569. ;; HImode multiply.
  570. ; The h8 only has an 8*8->16 multiply.
  571. ; The answer is the same as:
  572. ; product = (srca.l * srcb.l) + ((srca.h * srcb.l) + (srcb.h * srca.l)) * 256
  573. ; (we can ignore A1.h * A0.h cause that will all off the top)
  574. ; A0 in
  575. ; A1 in 
  576. ; A0 answer
  577.  
  578. #ifdef __H8300__
  579.     .section .text
  580.     .align 2
  581.     .global    ___mulhi3
  582. ___mulhi3:
  583.     mov.b    A1L,A2L        ; A2l gets srcb.l
  584.     mulxu    A0L,A2        ; A2 gets first sub product 
  585.  
  586.     mov.b    A0H,A3L        ; prepare for
  587.     mulxu    A1L,A3        ; second sub product
  588.  
  589.     add.b    A3L,A2H        ; sum first two terms
  590.  
  591.     mov.b    A1H,A3L        ; third sub product
  592.     mulxu    A0L,A3        
  593.  
  594.     add.b    A3L,A2H        ; almost there
  595.     mov.w    A2,A0        ; that is
  596.     rts
  597.  
  598. #endif
  599. #endif /* L_mulhi3 */
  600.  
  601. #ifdef L_mulsi3
  602.  
  603. ;; SImode multiply.
  604. ;; 
  605. ;; I think that shift and add may be sufficient for this.  Using the
  606. ;; supplied 8x8->16 would need 10 ops of 14 cycles each + overhead.  This way
  607. ;; the inner loop uses maybe 20 cycles + overhead, but terminates
  608. ;; quickly on small args.
  609. ;;
  610. ;; A0/A1 src_a
  611. ;; A2/A3 src_b
  612. ;;
  613. ;;  while (a) 
  614. ;;    {
  615. ;;      if (a & 1)
  616. ;;        r += b;
  617. ;;      a >>= 1;
  618. ;;      b <<= 1;
  619. ;;    }
  620.  
  621.     .section .text
  622.     .align 2
  623.  
  624. #ifdef __H8300__
  625.  
  626.     .global    ___mulsi3
  627. ___mulsi3:
  628.     PUSHP    S0P
  629.     PUSHP    S1P
  630.     PUSHP    S2P
  631.     
  632.     sub.w    S0,S0
  633.     sub.w    S1,S1
  634.     
  635.     ; while (a)
  636. _top:    mov.w    A0,A0
  637.     bne    _more
  638.     mov.w    A1,A1
  639.     beq    _done
  640. _more:    ; if (a & 1)
  641.     bld    #0,A1L
  642.     bcc    _nobit
  643.     ; r += b
  644.     add.w    A3,S1
  645.     addx    A2L,S0L
  646.     addx    A2H,S0H
  647. _nobit:
  648.     ; a >>= 1
  649.     shlr    A0H
  650.     rotxr    A0L
  651.     rotxr    A1H
  652.     rotxr    A1L
  653.     
  654.     ; b <<= 1
  655.     add.w    A3,A3
  656.     addx    A2L,A2L
  657.     addx    A2H,A2H
  658.     bra     _top
  659.  
  660. _done:
  661.     mov.w    S0,A0    
  662.     mov.w    S1,A1
  663.     POPP    S2P
  664.     POPP    S1P
  665.     POPP    S0P
  666.     rts
  667.  
  668. #else /* __H8300H__ */
  669.  
  670.     .h8300h
  671.  
  672.     .global    ___mulsi3
  673. ___mulsi3:
  674.     sub.l    A2P,A2P
  675.  
  676.     ; while (a)
  677. _top:    mov.l    A0P,A0P
  678.     beq    _done
  679.  
  680.     ; if (a & 1)
  681.     bld    #0,A0L
  682.     bcc    _nobit
  683.  
  684.     ; r += b
  685.     add.l    A1P,A2P
  686.  
  687. _nobit:
  688.     ; a >>= 1
  689.     shlr.l    A0P
  690.  
  691.     ; b <<= 1
  692.     shll.l    A1P
  693.     bra    _top
  694.  
  695. _done:
  696.     mov.l    A2P,A0P
  697.     rts
  698.  
  699. #endif
  700. #endif /* L_mulsi3 */
  701.